package com.yt.server.mode.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.yt.server.mode.api.ICommand;
import com.yt.server.mode.api.IController;
import com.yt.server.mode.api.IFunction;
import com.yt.server.mode.api.INotification;
import com.yt.server.mode.api.IObserver;
import com.yt.server.mode.patterns.observer.Observer;

/**
 * 控制层
 */
public class Controller implements IController {

	protected static Controller instance;
	protected Map<String, ICommand> commandMap;
	protected HashMap<String, List<IObserver>> observerMap;

	protected Controller() {
		instance = this;
		commandMap = new HashMap<String, ICommand>();
		observerMap = new HashMap<String, List<IObserver>>();
		initializeController();
	}

	protected void initializeController() {
	}

	public synchronized static Controller getInstance() {
		if (instance == null)
			instance = new Controller();

		return instance;
	}

	public void executeCommand(INotification note) {
		ICommand commandInstance = (ICommand) this.commandMap.get(note
				.getName());
		if (commandInstance != null) {
			commandInstance.handleNotification(note);
		}
	}

	public void registerCommand(final ICommand command) {
		if (this.commandMap.containsKey(command.getCommandName()))
			return;
		this.commandMap.put(command.getCommandName(), command);

		registerObserver(command.getCommandName(), new Observer(
				new IFunction() {
					public void onNotification(INotification notification) {
						executeCommand(notification);
					}
				}, this));
		command.onRegister();
	}

	public ICommand retrieveCommand(String commandName) {
		return (ICommand) this.commandMap.get(commandName);
	}

	public ICommand removeCommand(String commandName) {
		if (hasCommand(commandName)) {
			ICommand command = commandMap.get(commandName);
			removeObserver(commandName, this);
			commandMap.remove(commandName);
			command.onRemove();
			return command;
		}
		return null;
	}

	public boolean hasCommand(String commandName) {
		return commandMap.containsKey(commandName);
	}

	public void registerObserver(String notificationName, IObserver observer) {
		if (this.observerMap.get(notificationName) == null)
			this.observerMap.put(notificationName, new ArrayList<IObserver>());

		List<IObserver> observers = (List<IObserver>) this.observerMap
				.get(notificationName);
		observers.add(observer);
	}

	public void removeObserver(String notificationName, Object notifyContext) {
		List<IObserver> observers = observerMap.get(notificationName);
		if (observers != null) {
			for (int i = 0; i < observers.size(); i++) {
				Observer observer = (Observer) observers.get(i);
				if (observer.compareNotifyContext(notifyContext) == true)
					observers.remove(observer);
			}
			if (observers.size() == 0)
				observerMap.remove(notificationName);
		}
	}

	public void notifyObservers(INotification note) {
		List<IObserver> observers_ref = (List<IObserver>) observerMap.get(note
				.getName());
		if (observers_ref != null) {

			Object[] observers = (Object[]) observers_ref.toArray();

			for (int i = 0; i < observers.length; i++) {
				IObserver observer = (IObserver) observers[i];
				observer.notifyObserver(note);
			}
		}
	}
}